#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>




static dev_t dev_num;      // 设备号
struct cdev cdev_test;      // 字符设备
// 字符设备操作结构体
struct file_operations cdev_fops_test = {
    .owner = THIS_MODULE,
};
struct class *class_test;


static int __init chrdev_fops_init(void)
{
    int ret;
    int major,minor;
    
    // 申请设备号
    ret = alloc_chrdev_region(&dev_num, 0, 1, "chrdev-test");
    if (ret < 0)
    {
        printk(KERN_EMERG "alloc chrdev region error");
    }
    printk(KERN_EMERG "alloc chrdev region ok");
    major = MAJOR(dev_num);
    minor = MINOR(dev_num);
    printk(KERN_EMERG "major : %d \n minor : %d \r\n", major, minor);

    // 字符设备初始化，连接操作结构体
    cdev_init(&cdev_test, &cdev_fops_test);
    cdev_test.owner = THIS_MODULE;

    // 添加字符设备
    ret = cdev_add(&cdev_test, dev_num, 1);
    if (ret < 0)
    {
        printk(KERN_EMERG "cdev_add is error\n");
    }
    printk(KERN_EMERG "cdev_add is ok\n");

    // 创建类
    class_test = class_create(THIS_MODULE, "calss test");
    // 创建设备
    device_create(class_test, NULL, dev_num, NULL, "device_test") ;

    return 0;
}


static void __exit chrdev_fops_exit(void)
{
    device_destroy(class_test, dev_num);
    class_destroy(class_test);
    cdev_del(&cdev_test);  // 删除字符设备 
    unregister_chrdev_region(dev_num, 1);    // 释放设备号

    printk(KERN_EMERG "module eixt\r\n");
}


module_init(chrdev_fops_init);
module_exit(chrdev_fops_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Treasure");



